import BigWorld
import cPickle
import GUI
import json
import os
import csv
import codecs
import ResMgr
import math
import re
import game
import Keys
import string
import constants
import datetime
from items import vehicles as vehiclesWG
from CurrentVehicle import g_currentVehicle
from messenger.m_constants import BATTLE_CHANNEL
from ChatManager import chatManager
from gui.WindowsManager import g_windowsManager
from Avatar import PlayerAvatar
from ClientArena import ClientArena
from gui import g_guiResetters
from collections import defaultdict
from gui.Scaleform.Battle import Battle
from gui.Scaleform.Battle import VehicleMarkersManager
from gui.BattleContext import g_battleContext
from messenger import MessengerEntry
from items import vehicles
from Vehicle import Vehicle
from debug_utils import *
print '             expD v.2.2 by PiJey77 - Modified by mtm78'
class WotLabel(object):
    obj = None
    window = None
    shadow = {}
    label = {}
    MY_Labels = {}
    config = {}
    configOK = True
    csvOK = True
    MY_FirstTime = True
    MY_TankArray = {}
    MY_expDamage = 0
    MY_isNewDamage = False
    MY_Error = ''
    MY_WN8 = 0
    MY_EFF = 0
    MY_Hits = 0
    MY_CurrDamage = 0
    MY_Frags = 0
    MY_AvgDamage = 0
    MY_LastDamage = 0
    MY_TotalDamage = 0
    MY_LastTotalDamage = 0
    MY_LastTime = 0
    MY_typeDescriptor = 0
    MY_tank_Descr = defaultdict(dict)
    MY_expectedValues = {}
    def __init__(self):
        g_guiResetters.add(self.onChangeScreenResolution)
        res = ResMgr.openSection('../paths.xml')
        sb = res['Paths']
        vals = sb.values()[0:2]
        for vl in vals:
            path = vl.asString + '/scripts/client/mods/'
            if os.path.isdir(path):
                conf_file = path + 'expD.json'
                if os.path.isfile(conf_file):
                    try:
                        json_data = open(conf_file)
                        self.config = json.load(json_data)
                        json_data.close()
                    except ValueError:
                        self.configOK = False
                    continue
                continue
        for vl in vals:
            path = vl.asString + '/scripts/client/mods/'
            if os.path.isdir(path):
                expectedValuesPath = path + 'expD.csv'
                if os.path.isfile(expectedValuesPath):
                    try:
                        self.MY_TankArray = list(csv.reader(codecs.open(expectedValuesPath, encoding = 'cp1250')))
                    except ValueError:
                        self.csvOK = False
                else:
                    self.csvOK = False
                continue
        self.MY_LastTime = datetime.datetime.now()

    def __new__(self, *dt, **mp):
        if self.obj is None:
            self.obj = object.__new__(self, *dt, **mp)
        return self.obj

    @staticmethod
    def hexToRgba(hex):
        rgba = [int(hex[i:i + 2], 16) for i in range(1, 6, 2)]
        rgba.append(255)
        return tuple(rgba)

    def resetData(self):
        self.MY_expDamage = 0
        self.MY_isNewDamage = False
        self.MY_Error = ''
        self.MY_WN8 = 0
        self.MY_EFF = 0
        self.MY_Hits = 0
        self.MY_CurrDamage = 0
        self.MY_Frags = 0
        self.MY_AvgDamage = 0
        self.MY_LastDamage = 0
        self.MY_TotalDamage = 0
        self.MY_LastTotalDamage = 0
        self.MY_typeDescriptor = 0
        self.MY_tank_Descr = defaultdict(dict)
        self.MY_FirstTime = True

    def onChangeScreenResolution(self):
        if self.window is None:
            return
        else:
            sr = GUI.screenResolution()
            x = self.config.get('x')
            y = self.config.get('y')
            w = self.config.get('width')
            h = self.config.get('height')
            if x < 0:
                x = sr[0] + x - w
            if y < 0:
                y = sr[1] + y - h
            self.window.position = (x, y, 1)
            return

    def installItem(self, item, x, y):
        font = self.config.get('font')
        item.font = font
        self.window.addChild(item)
        item.verticalAnchor = 'TOP'
        item.horizontalAnchor = 'CENTER'
        item.horizontalPositionMode = 'PIXEL'
        item.verticalPositionMode = 'PIXEL'
        item.position = (x, y, 1)

    def errorMessage(self, message):
        self.window = GUI.Window('')
        self.window.colour = (255, 255, 255, 255)
        self.window.materialFX = 'BLEND'
        self.window.verticalAnchor = 'TOP'
        self.window.horizontalAnchor = 'LEFT'
        self.window.horizontalPositionMode = 'PIXEL'
        self.window.verticalPositionMode = 'PIXEL'
        self.window.heightMode = 'PIXEL'
        self.window.widthMode = 'PIXEL'
        self.window.width = 500
        self.window.height = 100
        GUI.addRoot(self.window)
        self.label[1] = GUI.Text(message)
        self.label[1].colour = (255, 255, 255, 255)
        self.window.addChild(self.label[1])
        self.label[1].font = 'default_small.font'
        self.label[1].verticalAnchor = 'TOP'
        self.label[1].horizontalAnchor = 'CENTER'
        self.label[1].horizontalPositionMode = 'PIXEL'
        self.label[1].verticalPositionMode = 'PIXEL'
        self.label[1].position = (200, 10, 1)
        self.window.position = (200, 200, 1)
        self.window.visible = True
        self.label[1].visible = True

    def createLabel(self):
        if self.configOK != True:
            text = 'expD error in expD.json file.'
            MessengerEntry.g_instance.gui.addClientMessage(text)
            return
        elif self.csvOK != True:
            text = 'expD error: in expD.csv file.'
            MessengerEntry.g_instance.gui.addClientMessage(text)
            return
        else:
            if self.config.get('background') == 'True':
                background = os.path.join('scripts', 'client', 'mods', 'expD.dds')
            else:
                background = ''
            self.window = GUI.Window(background)
            self.window.colour = (255, 255, 255, 255)
            self.window.materialFX = 'BLEND'
            self.window.verticalAnchor = 'TOP'
            self.window.horizontalAnchor = 'LEFT'
            self.window.horizontalPositionMode = 'PIXEL'
            self.window.verticalPositionMode = 'PIXEL'
            self.window.heightMode = 'PIXEL'
            self.window.widthMode = 'PIXEL'
            self.window.width = self.config.get('width')
            self.window.height = self.config.get('height')
            GUI.addRoot(self.window)
            self.MY_Labels = self.config.get('labels')
            for z in xrange(0, len(self.MY_Labels)):
                x = self.MY_Labels[z]['x']
                y = self.MY_Labels[z]['y']
                self.shadow[z] = GUI.Text('')
                self.shadow[z].colour = (0, 0, 0, 255)
                self.installItem(self.shadow[z], x + 1, y + 1)
                self.label[z] = GUI.Text('')
                self.label[z].colour = (255, 255, 255, 255)
                self.installItem(self.label[z], x, y)
            self.onChangeScreenResolution()
            return

    def deleteLabel(self):
        GUI.delRoot(self.window)
        self.window = None

    def updateDamage(self, Victim, xDamage, attack):
        self.MY_TotalDamage = self.MY_TotalDamage + xDamage
        timeX = self.MY_LastTime
        timeY = datetime.datetime.now()
        if timeY - timeX > datetime.timedelta(0, 1.5):
            self.MY_LastTime = datetime.datetime.now()
            self.MY_isNewDamage = True
        else:
            self.MY_isNewDamage = False
        if attack == 0:
            self.MY_Hits = self.MY_Hits + 1
        self.MY_LastDamage = xDamage
        self.update()

    def calcWN8(self, xDamage, expectedDamage, rSPOT, rFRAG, frags, rDEF, rWIN):
        rDAMAGE = float(xDamage) / float(expectedDamage)
        rSPOT = 0 / float(rSPOT)
        rFRAG = float(frags) / float(rFRAG)
        rDEF = 0 / float(rDEF)
        rWIN = 0 / float(rWIN)
        rWINc = max(0, int(rWIN) - 0.71 / 0.29000000000000004)
        rDAMAGEc = max(0, (rDAMAGE - 0.22) / 0.78)
        rFRAGc = max(0, min(rDAMAGEc + 0.2, (rFRAG - 0.12) / 0.88))
        rSPOTc = max(0, min(rDAMAGEc + 0.1, (rSPOT - 0.38) / 0.62))
        rDEFc = max(0, min(rDAMAGEc + 0.1, (rDEF - 0.1) / 0.9))
        WN8 = 980 * rDAMAGEc + 210 * rDAMAGEc * rFRAGc + 155 * rFRAGc * rSPOTc + 75 * rDEFc * rFRAGc + 145 * min(1.8, rWINc)
        return WN8

    def calcEFF(self, xDamage, rSPOT, rFRAG, frags, rDEF, rWIN, rTIER):
        avgDamage = float(xDamage)
        avgFrag = float(frags)
        avgSpot = float(rSPOT)
        avgDef = float(rDEF)
        avgCap = float(0)
        avgTier = float(rTIER)
        EFF = max(0, int(avgDamage * 10 / (avgTier + 2) * (0.23 + 2 * avgTier / 100) + avgFrag * 250 + avgSpot * 150 + math.log(avgCap + 1, 1.732) * 150 + avgDef * 150))
        return EFF

    def checkMacros(self, text):
        if '{{totalDMG}}' in text:
            text = text.replace('{{totalDMG}}', str(self.MY_TotalDamage))
        if '{{WN8}}' in text:
            text = text.replace('{{WN8}}', str(int(self.MY_WN8)))
        if '{{EFF}}' in text:
            text = text.replace('{{EFF}}', str(int(self.MY_EFF)))
        if '{{diff}}' in text:
            text = text.replace('{{diff}}', str(int(self.MY_CurrDamage)))
        if '{{hits}}' in text:
            text = text.replace('{{hits}}', str(int(self.MY_Hits)))
        if '{{frags}}' in text:
            text = text.replace('{{frags}}', str(int(self.MY_Frags)))
        if '{{avgDMG}}' in text:
            text = text.replace('{{avgDMG}}', str(int(self.MY_AvgDamage)))
        if '{{lastDMG}}' in text:
            text = text.replace('{{lastDMG}}', str(int(self.MY_LastDamage)))
        return text

    def checkColor(self, Ccolor):
        labelcolor = Ccolor
        if Ccolor == '{{diff}}':
            if self.MY_CurrDamage < 0:
                labelcolor = '#FF0000'
            if self.MY_CurrDamage == 0:
                labelcolor = '#67C8FF'
            if self.MY_CurrDamage > 0:
                labelcolor = '#00FF00'
        if Ccolor == '{{WN8}}':
            colorsWN8 = self.config.get('colorsWN8')
            for wn8Color in colorsWN8:
                if self.MY_WN8 >= wn8Color['value']:
                    labelcolor = wn8Color['color']
                    continue
                else:
                    break
                    continue
            else:
                pass
        elif Ccolor == '{{EFF}}':
            colorsEFF = self.config.get('colorsEFF')
            for effColor in colorsEFF:
                if self.MY_EFF >= effColor['value']:
                    labelcolor = effColor['color']
                    continue
                else:
                    break
                    continue
            else:
                pass
        return labelcolor

    def CheckBattleType(self):
        player = BigWorld.player()
        battleType = player.arena.guiType
        battleTypeName = ''
        if battleType == constants.ARENA_GUI_TYPE.RANDOM:
            battleTypeName = 'Random'
        elif battleType == constants.ARENA_GUI_TYPE.TRAINING:
            battleTypeName = 'Training'
        elif battleType == constants.ARENA_GUI_TYPE.COMPANY:
            battleTypeName = 'Company'
        elif battleType == constants.ARENA_GUI_TYPE.CYBERSPORT:
            battleTypeName = 'CyberSport'
        else:
            battleTypeName = 'ClanWar'
        return battleTypeName

    def PassTypeDescr(self, typeDescriptor):
        self.MY_typeDescriptor = typeDescriptor

    def update(self):
        if self.window is None:
            return
        elif self.configOK != True:
            text = 'expD error in expD.json file.'
            MessengerEntry.g_instance.gui.addClientMessage(text)
            return
        elif self.csvOK != True:
            text = 'expD error: in expD.csv file.'
            MessengerEntry.g_instance.gui.addClientMessage(text)
            return
        else:
            player = BigWorld.player()
            ownID = BigWorld.player().playerVehicleID
            current = player.arena.vehicles.get(ownID)
            VehicleFullName = current['vehicleType'].type.userString
            self.MY_Frags = len(BigWorld.player()._PlayerAvatar__frags)
            self.MY_expDamage = 0
            self.MY_WN8 = 0
            self.MY_EFF = 0
            self.MY_Error = 'Error'
            self.MY_AvgDamage = 0
            self.MY_CurrDamage = 0
            currTank = ''
            keys = len(self.MY_TankArray)
            for xx in xrange(1, keys):
                if self.MY_typeDescriptor != 0:
                    if self.MY_typeDescriptor.type.id[0] == int(self.MY_TankArray[xx][9]) >> 4 & 15 and self.MY_typeDescriptor.type.id[1] == int(self.MY_TankArray[xx][9]) >> 8 & 65535:
                        self.MY_expDamage = self.MY_TankArray[xx][2]
                        rSPOT = self.MY_TankArray[xx][3]
                        rFRAG = self.MY_TankArray[xx][1]
                        rDEF = self.MY_TankArray[xx][4]
                        rWIN = self.MY_TankArray[xx][5]
                        rTIER = self.MY_TankArray[xx][6]
                        self.MY_WN8 = self.calcWN8(self.MY_TotalDamage, self.MY_expDamage, rSPOT, rFRAG, self.MY_Frags, rDEF, rWIN)
                        self.MY_EFF = self.calcEFF(self.MY_TotalDamage, rSPOT, rFRAG, self.MY_Frags, rDEF, rWIN, rTIER)
                        self.MY_Error = ''
                        break
                    continue
            if self.MY_Error == 'Error':
                text = 'expD error: no data for current tank'
                MessengerEntry.g_instance.gui.addClientMessage(text)
            self.MY_CurrDamage = float(self.MY_TotalDamage) - float(self.MY_expDamage)
            if self.MY_Hits > 0:
                self.MY_AvgDamage = float(self.MY_TotalDamage) / float(self.MY_Hits)
            else:
                self.MY_AvgDamage = 0
            self.MY_Labels = self.config.get('labels')
            for z in xrange(0, len(self.MY_Labels)):
                x = self.MY_Labels[z]['x']
                y = self.MY_Labels[z]['y']
                color = self.checkColor(self.MY_Labels[z]['color'])
                text = self.checkMacros(self.MY_Labels[z]['value'])
                if self.config.get('shadow') == 'True':
                    self.shadow[z].text = text
                    self.shadow[z].colour = self.hexToRgba(self.config.get('shadow_color'))
                elif self.config.get('shadow') == 'False':
                    self.shadow[z].text = ''
                self.label[z].text = text
                self.label[z].colour = self.hexToRgba(color)
            if self.MY_isNewDamage == True:
                if self.CheckBattleType() == 'Random' and self.config.get('putMyRandomMessage') == 'True':
                    from messenger.gui.messengerDispatcher import g_instance as g_MsgDispatcher
                    if g_MsgDispatcher.channels.hasSquadChannel():
                        text = self.checkMacros(self.config.get('MyRandomMessage'))
                        player.broadcast(g_MsgDispatcher.channels.getSquadChannel().cid, text.encode('utf8', 'xmlcharrefreplace'))
                    self.MY_isNewDamage = False
                if self.CheckBattleType() == 'Training' and self.config.get('putMyTrainingMessage') == 'True':
                    text = self.checkMacros(self.config.get('MyTrainingMessage'))
                    self.MY_isNewDamage = False
                    player.broadcast(chatManager.battleTeamChannelID, text.encode('utf8', 'xmlcharrefreplace'))
                if self.CheckBattleType() == 'Company' and self.config.get('putMyCompanyMessage') == 'True':
                    text = self.checkMacros(self.config.get('MyCompanyMessage'))
                    self.MY_isNewDamage = False
                    player.broadcast(chatManager.battleTeamChannelID, text.encode('utf8', 'xmlcharrefreplace'))
                if self.CheckBattleType() == 'CyberSport' and self.config.get('putMyCyberSportMessage') == 'True':
                    text = self.checkMacros(self.config.get('MyCyberSportMessage'))
                    self.MY_isNewDamage = False
                    player.broadcast(chatManager.battleTeamChannelID, text.encode('utf8', 'xmlcharrefreplace'))
                if self.CheckBattleType() == 'ClanWar' and self.config.get('putMyClanWarMessage') == 'True':
                    text = self.checkMacros(self.config.get('MyClanWarMessage'))
                    self.MY_isNewDamage = False
                    player.broadcast(chatManager.battleTeamChannelID, text.encode('utf8', 'xmlcharrefreplace'))
            return

    def setVisible(self, flag):
        self.window.visible = flag
        for z in xrange(0, len(self.MY_Labels)):
            self.shadow[z].visible = flag
            self.label[z].visible = flag

old_PlayerAvatar_setVisibleGUI = PlayerAvatar._PlayerAvatar__setVisibleGUI
def new_PlayerAvatar_setVisibleGUI(self, bool):
    old_PlayerAvatar_setVisibleGUI(self, bool)
    expDamageLabel.setVisible(bool)

PlayerAvatar._PlayerAvatar__setVisibleGUI = new_PlayerAvatar_setVisibleGUI
old_Battle_afterCreate = Battle.afterCreate
def new_Battle_afterCreate(self):
    old_Battle_afterCreate(self)
    expDamageLabel.createLabel()
    expDamageLabel.update()

Battle.afterCreate = new_Battle_afterCreate
old_Battle_beforeDelete = Battle.beforeDelete
def new_beforeDelete(self):
    expDamageLabel.resetData()
    old_Battle_beforeDelete(self)
    expDamageLabel.deleteLabel()

Battle.beforeDelete = new_beforeDelete
old_Vehicle_onEnterWorld = Vehicle.onEnterWorld
def new_Vehicle_onEnterWorld(self, prereqs):
    old_Vehicle_onEnterWorld(self, prereqs)
    player = BigWorld.player()
    __vID = BigWorld.player().playerVehicleID
    vehicle = BigWorld.entity(__vID)
    for key, vehicle in player.arena.vehicles.iteritems():
        if vehicle['name'] == self.publicInfo.name:
            self.__battleID = key
            expDamageLabel.MY_tank_Descr[self.__battleID]['currentHealth'] = BigWorld.entity(self.__battleID).health
            break
            continue
    if self.__battleID == __vID:
        typeDescriptor = vehicles.VehicleDescr(compactDescr = self.publicInfo.compDescr)
        expDamageLabel.PassTypeDescr(typeDescriptor)
    expDamageLabel.update()

Vehicle.onEnterWorld = new_Vehicle_onEnterWorld
old_Vehicle_onHealthChanged = Vehicle.onHealthChanged
def new_Vehicle_onHealthChanged(self, newHealth, attackerID, attackReasonID):
    old_Vehicle_onHealthChanged(self, newHealth, attackerID, attackReasonID)
    if 'currentHealth' in expDamageLabel.MY_tank_Descr[self.__battleID]:
        __Damage = expDamageLabel.MY_tank_Descr[self.__battleID]['currentHealth'] - newHealth
        expDamageLabel.MY_tank_Descr[self.__battleID]['currentHealth'] = newHealth
        __vID = BigWorld.player().playerVehicleID
        if __vID == attackerID:
            expDamageLabel.updateDamage(self.__battleID, __Damage, attackReasonID)

Vehicle.onHealthChanged = new_Vehicle_onHealthChanged
expDamageLabel = WotLabel()

